<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>VC知识库</title>
</head>

<body>

<div align="justify">
	<table class="font" height="57" width="100%" border="0">
		<tr>
			<td class="bigfont" borderColor="#800080" align="middle" width="27%" bgColor="#b8cfe7" height="6">
			<font color="#800080">VC知识库（五）</font> </td>
			<td class="bigfont" borderColor="#800080" align="middle" width="73%" bgColor="#b8cfe7" height="6">
			<font color="#800080">www.vckbase.com</font> </td>
		</tr>
		<tr>
			<td class="header" vAlign="top" align="middle" width="100%" colSpan="2" height="4">
			<hr></td>
		</tr>
		<tr>
			<td class="header" vAlign="top" align="middle" width="100%" colSpan="2" height="17">
			<small>
			<p align="center"><big>VC++5.0下使用ActiveX控件的问题</big></small></td>
		</tr>
		<tr>
			<td class="info" align="middle" width="100%" colSpan="2" height="17">
			<small><big><font face="宋体">刘芳 周顺平</font></big></small> </td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="22"><hr></td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="5"><small>
			<table width="80%" align="center" border="0">
				<tr>
					<td>
					自从Microsoft最早在1996年3月的Internet专业开发人员研讨会上提出ActiveX一词以来，到今天已有无数公司的无数产品中涉及了ActiveX技术，而作为ActiveX技术之一的ActiveX控件，更是得到广大开发者的青睐。那么，到底什么是ActiveX控件呢？</td>
				</tr>
				<tr>
					<td>
					一方面，它表示将你带向Microsoft、Internet和业界的新技术的小型快速的可重用组件。它与开发语言无关，在任何支持ActiveX控件的软件开发平台（如VB、VC++、Access、VFP、Delphi、PowerBuilder等）上都可以使用ActiveX控件，程序员可以像使用Windows标准控件一样使用不同厂商开发的ActiveX控件。这样就实现了软件开发的工业化，大大地提高了软件的生产效率。</td>
				</tr>
				<tr>
					<td>
					另一方面，它代表Internet与应用程序的一种集成策略。用户可以从Internet上下载ActiveX控件，也可以通过网络在本地机上调用远程机上的ActiveX控件，还可以将ActiveX控件加入到Internet主页上。 
					既然ActiveX控件对程序员是如此地重要，那么如何用好ActiveX控件也就成为软件开发者所关心的问题。本文以VC++5.0为开发工具，以一个项目名为Test的应用程序为例，针对笔者在控件使用中遇到的一些问题加以讨论。</td>
				</tr>
				<tr>
					<td>&nbsp;</td>
				</tr>
				<tr bgColor="#ffcc66">
					<td><font face="楷体_GB2312">一．使应用程序支持ActiveX控件</font></td>
				</tr>
				<tr>
					<td>要想在应用程序中使用ActiveX控件，必须使你的应用程序成为ActiveX控件包容器。ActiveX 
					控件包容器就是完全支持ActiveX控件，并能把控件组合进自己的窗口或对话框的父应用程序。利用MFC的AppWizard，你可以很方便地创建你的包容器程序。事实上，在用AppWizard创建新的应用程序时，你的应用程序就被缺省设置为控件包容器，即使你在创建过程中没有加入ActiveX控件支持，以后也可以手动地进行更改。</td>
				</tr>
				<tr>
					<td>
					1、在项目的应用类的.cpp文件（本例中为test.cpp）的Initinstance函数中加入对函数AfxEnableControlContainer()的调用，如下所示：</td>
				</tr>
				<tr>
					<td>BOOL CTestApp::InitInstance()
					<p>{ </p>
					<p>AfxEnableControlContainer(); </p>
					<p>... </p>
					<p>}</td>
				</tr>
				<tr>
					<td>2、在项目中的STDAFX.H头文件中加入如下代码：#include &lt;afxdisp.h&gt;<AFXDISP.H> 
					然后重新链接项目即可。</td>
				</tr>
				<tr>
					<td><AFXDISP.H></td>
				</tr>
				<tr bgColor="#ffcc66">
					<td><font face="楷体_GB2312">二．在非对话框容器中使用ActiveX控件</font></td>
				</tr>
				<tr>
					<td>在使用一个已注册的ActiveX控件之前，必须先用组件廊将该控件添加到应用程序中：</td>
				</tr>
				<tr>
					<td>1、从Project菜单中选择Add To Project下的Components and Controls。</td>
				</tr>
				<tr>
					<td>2、在弹出的对话框中双击并打开Registered ActiveX Control子目录。</td>
				</tr>
				<tr>
					<td>3、选择你需要的控件，点击Insert按钮，弹出Confirm Classes对话框。</td>
				</tr>
				<tr>
					<td>4、在列出的类名中选择需要的类（缺省为全选中，最好接受缺省设置），点击OK，关闭Confirm 
					Classes对话框。</td>
				</tr>
				<tr>
					<td>5、点击Close关闭组件廊，则该控件的图标即加入到对话框编辑器的控件面板上。</td>
				</tr>
				<tr>
					<td>
					这样，我们就可以在对话框中像使用Windows标准控件那样使用该控件了。但在某些应用中，你可能需要在非对话框容器（如应用程序的窗口）中嵌入ActiveX控件。这时没有对话框编辑器，我们应怎样在非对话框容器中使用ActiveX控件呢？</td>
				</tr>
				<tr>
					<td>当组件廊将ActiveX控件添加到你的应用程序后，组件廊会创建一些包裹类（即在Confirm 
					Classes对话框中列出的那些类）。其中有一个类的基类是CWnd，该类是控件的包裹类，它被用作控件与控件包容器之间的接口,有两个公有的Create成员函数：</td>
				</tr>
				<tr>
					<td>virtual BOOL Create(LPCTSTR lpszClassName,<p>LPCTSTR 
					lpszWindowName, DWORD dwStyle,</p>
					<p>const RECT&amp; rect, CWnd* pParentWnd, UINT nID,</p>
					<p>CCreateContext* pContext = NULL)</td>
				</tr>
				<tr>
					<td>和BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,<p>
					const RECT&amp; rect, CWnd* pParentWnd, UINT nID,</p>
					<p>CFile* pPersist = NULL, BOOL bStorage = FALSE,</p>
					<p>BSTR bstrLicKey = NULL)</td>
				</tr>
				<tr>
					<td>我们就可以使用该控件的包裹类的Create函数在非对话框容器中动态地创建此控件的实例。</td>
				</tr>
				<tr>
					<td>具体步骤如下：（本例中欲加入的控件名为MSFlexGrid 
					，CMSFlexGrid是控件的包裹类，msflexgrid.h是包裹类的头文件）</td>
				</tr>
				<tr>
					<td>1、在视类头文件（本例中为TestView.h）中的类定义前加上<p>#include msflexgrid.h</td>
				</tr>
				<tr>
					<td>2、在TestView.h中CTestView类定义的protected部分加上控件包裹类类型的成员变量声明：</td>
				</tr>
				<tr>
					<td>class CTestView : public CView
					<p>{ </p>
					<p>... </p>
					<p>protected: </p>
					<p>CMSFlexGrid m_fgrid; </p>
					<p>... </p>
					<p>};</td>
				</tr>
				<tr>
					<td>3、用ClassWizard为类CTestView 添加消息WM_CREATE的处理函数CTestView::OnCreate，在此函数中，调用控件类CMSFlexGrid的Create函数：</td>
				</tr>
				<tr>
					<td>int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
					<p>{ </p>
					<p>if (CView::OnCreate(lpCreateStruct) == -1) return -1; </p>
					<p>// ****** Add your code below this line ********** //</p>
					<p>m_fgrid.Create(NULL, WS_VISIBLE, </p>
					<p>CRect(50,50,100,100), this, 0);//用this指针作为指向父窗口的指针//</p>
					<p>m_fgrid.SetCols(2); </p>
					<p>m_fgrid.SetRows(10); </p>
					<p>m_fgrid.SetTextMatrix(0,0,&quot;序号&quot;); </p>
					<p>m_fgrid.SetTextMatrix(0,1,&quot;姓名&quot;); // ****** Add your code 
					above this line ********** // </p>
					<p>return 0; </p>
					<p>}</td>
				</tr>
				<tr>
					<td>4、重新链接工程，运行。可以看到当应用程序的视窗生成时，控件也动态地生成了。</td>
				</tr>
				<tr>
					<td>5、如果你以后还想改变控件的位置和大小，可以继承CWnd::MoveWindow()函数。例如，若想使控件充满整个窗口，并在父窗口移动和缩放时也随之移动和缩放，可以添加消息WM_SIZE的处理函数OnSize，并加入如下代码：</td>
				</tr>
				<tr>
					<td>void CTestView::OnSize(UINT nType, int cx, int cy)<p>
					CView::OnSize(nType, cx, cy); // TODO: Add your message 
					handler code here// </p>
					<p>m_fgrid.MoveWindow(0,0,cx,cy); </td>
				</tr>
				<tr>
					<td>&nbsp;</td>
				</tr>
				<tr bgColor="#ffcc66">
					<td><font face="楷体_GB2312">三、在对话框中使用运行时不可见的ActiveX控件</font></td>
				</tr>
				<tr>
					<td>通常情况下，我们可以用两种方法来存取对话框中的控件：</td>
				</tr>
				<tr>
					<td>1、将控件与对话框的成员变量相关联，通过对话框数据交换DDX来实现控件和对应的成员变量之间的数据交换（详情请参阅VC联机帮助ActiveX 
					Control Containers: Connecting an ActiveX Control to a 
					Member Variable）</td>
				</tr>
				<tr>
					<td>2、调用函数CWnd::GetDlgItem来取得指向控件的指针。</td>
				</tr>
				<tr>
					<td>
					有些ActiveX控件没有用户界面，在运行时不可见。如果你在对话框中加入了运行时不可见的ActiveX控件，并想用CWnd::GetDlgItem来存取此控件，则此控件将不能正常工作。要得到代表此控件的对象指针，可采取以下两种方法之一：</td>
				</tr>
				<tr>
					<td>1、在ClassWizard的成员变量标签中，选择此控件的ID，点击Add 
					Variable，然后输入一个成员变量名，在Category中选择Control，在Variable 
					type中选择控件类。</td>
				</tr>
				<tr>
					<td>
					2、声明一个此控件类型的局部变量，并将它作为一个对话框项。加入类似如下所列的代码（其中CmyCtrl是控件类，IDMYCTRL1是控件ID）：</td>
				</tr>
				<tr>
					<td>CMyCtrl myCtrl;
					<p>myCtrl.SubclassDlgItem(IDC_MYCTRL1, this); // ... 
					使用控件myCtrl ... //</p>
					<p>myCtrl.UnsubclassWindow();</td>
				</tr>
				<tr bgColor="#ffffff">
					<td>&nbsp;</td>
				</tr>
				<tr bgColor="#ffcc66">
					<td><font face="楷体_GB2312">下面举一个例子加以说明</font></td>
				</tr>
				<tr>
					<td>本例将在对话框中加入一个运行时不可见的计时控件Timer Object。该控件在一个的预定的时间间隔过去之后引发 
					Timer 事件，该时间间隔储存于该控件的Interval 
					属性中，它以千分之一秒为单位指定时间的长度。本例用一个成员变量m_num来计数，每隔一个Interval时间递增1，当m_num计到10时，重置为0，并将时间间隔m_Interval增加200毫秒，并分别在两个静态框中显示当前的m_num和m_Interval。步骤如下：</td>
				</tr>
				<tr>
					<td>1、用组件廊将Timer控件加入到项目Test中。</td>
				</tr>
				<tr>
					<td>2、在项目中插入一个新的对话框，类名为CTestDlg。</td>
				</tr>
				<tr>
					<td>3、在对话框模板中加入控件Timer 
					Object（包裹类为CIeTimer），如图2的右下角。打开属性对话框，设置ID为IDC_TIMER1。再切换至All属性页，设置Interval为200。</td>
				</tr>
				<tr>
					<td>4、在对话框模板中添加静态控件，Caption为“The current interval is：”。</td>
				</tr>
				<tr>
					<td>
					5、添加一个不带Caption的静态控件，打开属性对话框，设置ID为IDC_STATIC1。再切换至Extended 
					Styles属性页，选中Static edge复选框。</td>
				</tr>
				<tr>
					<td>6、按下Ctrl键的同时双击静态控件IDC_STATIC1，弹出Add Member 
					Variable对话框，第一项中填写变量名m_text1，Category项中选择Control，Variable 
					type项中选择CStatic。</td>
				</tr>
				<tr>
					<td>7、添加静态控件&quot;The current number is:&quot;。</td>
				</tr>
				<tr>
					<td>
					8、重复步骤5到步骤6，添加一个不带Caption的静态控件（ID为IDC_STATIC2），变量名为m_text2。</td>
				</tr>
				<tr>
					<td>9、运行ClassWizard并选择Message Map属性页，在Class name 
					中选择CTestDlg，Object IDs中选择IDC_TIMER1，在Messages中选择Timer，点击Add 
					Function…按钮，加入OnTimerTimer1()处理函数。 
					</td>
				</tr>
				<tr>
					<td>
					采用第一种方法，则按前面所述步骤用ClassWizard给此控件类添加一个成员变量m_timer,并在OnTimerTimer1函数中添加如下代码：</td>
				</tr>
				<tr>
					<td>void CTestDlg::OnTimerTimer1() // TODO: Add your control 
					notification handler code here //<p>char buf[10]; </p>
					<p>m_num++; </p>
					<p>if(m_num&gt;=10) </p>
					<p>{ </p>
					<p>m_num=0;</p>
					<p>m_interval+=200; </p>
					<p>m_timer.SetInterval(m_interval); </p>
					<p>} </p>
					<p>_itoa(m_interval,buf,10); </p>
					<p>m_text1.SetWindowText (buf); </p>
					<p>_itoa(m_num,buf,10); </p>
					<p>m_text2.SetWindowText (buf);</td>
				</tr>
				<tr>
					<td>&nbsp;</td>
				</tr>
				<tr>
					<td>若采用第二种方法，则不需要添加此控件类的成员变量，只需将加灰显示的语句用下列语句代替即可：</td>
				</tr>
				<tr>
					<td>CIeTimer m_timer;
					<p>m_timer.SubclassDlgItem(IDC_TIMER1,this); </p>
					<p>m_timer.SetInterval(m_interval); </p>
					<p>m_timer.UnsubclassWindow();</td>
				</tr>
				<tr>
					<td>运行之后可以看到计数的步调越来越慢了（因为时间间隔越来越大）</td>
				</tr>
				<tr>
					<td>&nbsp;</td>
				</tr>
				<tr>
					<td>
					ActiveX控件大大地简化了开发者的工作，灵活地使用控件能使开发者高效地开发出各种软件。以上是笔者在使用控件的过程中总结出的一些实践经验，希望对大家有所帮助。</td>
				</tr>
			</table>
			<p>　 </small></td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="12"></td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="6"></td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="8"></td>
		</tr>
		<tr>
			<td class="font" width="100%" colSpan="2" height="17"></td>
		</tr>
	</table>
</div>

</body>

</html>
